﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;

using Uniriotec.DC.RTSP;

namespace Uniriotec.DC.ClientProgram
{
    public partial class ClientForm : Form
    {
        #region Private Fields

        private Client client = new Client();
        private static int RTSP_server_port;
        private static String ServerHost;
        private bool positionChanged = false;
        private int lastFrameReceived = 0;
        private string videoFilename = "movie.mjpeg";

        #endregion

        #region Delegates
        
        public delegate void DelegateRefreshSliderPosition();
        public DelegateRefreshSliderPosition RefreshSliderPosition;

        #endregion

        #region Constructor

        public ClientForm()
        {
            InitializeComponent();
            client.RtspConnectionState = RtspStates.DISCONNECTED;

            client.ConnectionStateChanged += new EventHandler(client_ConnectionStateChanged);
            client.RTPPacketReceived += new EventHandler<RTPPacketReceivedEventArgs>(client_RTPPacketReceived);

            // Refresh the slider position on the UI thread.
            RefreshSliderPosition = delegate() { this.trackBar1.Value = (int)(lastFrameReceived / 10); };

        }

        #endregion

        #region Buttons

        /// <summary>
        /// Handler for Connect button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void connectButton_Click(object sender, EventArgs e)
        {
            if (client.RtspConnectionState == RtspStates.DISCONNECTED)
            {
                statusLabel.Text = "Connecting";

                RTSP_server_port = (int)portSelectionbox.Value;
                ServerHost = serverTextbox.Text;

                client.Connect(ServerHost, RTSP_server_port);
            }
        }

        /// <summary>
        /// Handler for Setup button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void setupButton_Click(object sender, EventArgs e)
        {

            if (client.RtspConnectionState == RtspStates.INIT)
            {
                //Init non-blocking RTPsocket that will be used to receive data
                try
                {
                    client.PrepareToReceiveVideo();
                }
                catch (SocketException se)
                {
                    Console.Out.WriteLine("Socket exception: " + se);
                }

                client.VideoFileName = this.videoFilename;

                //Send SETUP message to the server
                client.send_RTSP_request(RTSPAction.SETUP);

                //Wait for the response 
                if (client.parse_server_response() != 200)
                    Console.Out.WriteLine("Invalid Server Response");
                else
                {
                    //change RTSP state and print new state 
                    client.RtspConnectionState = RtspStates.READY;
                }
            }//else if state != INIT then do nothing
        }

        /// <summary>
        /// Handler for Play button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void playButton_Click(object sender, EventArgs e)
        {

            if (client.RtspConnectionState == RtspStates.READY)
            {

                if (!positionChanged)
                {
                    //Send PLAY message to the server
                    client.send_RTSP_request(RTSPAction.PLAY);

                }
                else
                {
                    //Next Expected Frame
                    lastFrameReceived = trackBar1.Value * 10;

                    //Send PLAY message asking for a specific start
                    client.send_RTSP_request(RTSPAction.PLAY, trackBar1.Value);
                    positionChanged = false;
                }

                //Wait for the response 
                if (client.parse_server_response() != 200)
                    Console.Out.WriteLine("Invalid Server Response");
                else
                {
                    //change RTSP state and print out new state
                    client.RtspConnectionState = RtspStates.PLAYING;

                    client.StartReceivingVideo();
                }
            }//else if state != READY then do nothing

        }
        /// <summary>
        /// Handler for Pause button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pauseButton_Click(object sender, EventArgs e)
        {
            if (client.RtspConnectionState == RtspStates.PLAYING)
            {

                //Send PAUSE message to the server
                client.send_RTSP_request("PAUSE");

                //Wait for the response 
                if (client.parse_server_response() != 200)
                    Console.Out.WriteLine("Invalid Server Response");
                else
                {
                    //change RTSP state and print out new state
                    client.RtspConnectionState = RtspStates.READY;

                    client.PauseReceivingVideo();
                }
            }

            //else if state != PLAYING then do nothing

        }

        /// <summary>
        /// Handler for Teardown button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void teardownButton_Click(object sender, EventArgs e)
        {
            if (client.RtspConnectionState == RtspStates.DISCONNECTED
                ||
                client.RtspConnectionState == RtspStates.INIT
               )
                return;

            lastFrameReceived = 0;

            //Send TEARDOWN message to the server
            client.send_RTSP_request(RTSPAction.TEARDOWN);

            //Wait for the response 
            if (client.parse_server_response() != 200)
                Console.Out.WriteLine("Invalid Server Response");
            else
            {
                //change RTSP state
                client.RtspConnectionState = RtspStates.DISCONNECTED;

                client.DoTearDown();
                //exit
            }

        }

        #endregion

        #region Methods

        private void client_RTPPacketReceived(object sender, RTPPacketReceivedEventArgs e)
        {
            DisplayFrameReceived(e.Packet);
            lastFrameReceived = e.Packet.SequenceNumber;
            Invoke(RefreshSliderPosition);
        }

        private void DisplayFrameReceived(RTPpacket packet)
        {
            Image image = packet.GetPayloadAsImage();
            MovieBox.Image = image;
        }

        private void client_ConnectionStateChanged(object sender, EventArgs e)
        {
            statusLabel.Text = GetStatusString(client.RtspConnectionState);
        }

        private string GetStatusString(RtspStates state)
        {
            string status = String.Empty;

            switch (state)
            {
                case RtspStates.DISCONNECTED: status = "Disconnected"; break;
                case RtspStates.INIT: status = "Connected"; break;
                case RtspStates.PLAYING: status = "Playing"; break;
                case RtspStates.READY: status = "Ready"; break;
            }
            return status;
        }

        private void ClientForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            positionChanged = true;
        }

        #endregion

    }



}
